<?php
require_once SITE_ROOT_PATH."/_lib/base/curl_multirequest.php";
require_once SITE_ROOT_PATH.'/_lib/classes/Supplier/low/class.QueryBuilder.php';

class supplier {

    protected $code;
    protected $name;
    protected $account;
    protected $method;
    protected $services;
    protected $search_params_map;
    protected $booking_params_map;
         
    public function __construct($params) {
  
    // store supplier configuration
    $this->code = (string)$params["code"];
    $this->name = (string)$params["name"];
    $this->auth = array( "username_name"=>(string)$params->account->username["name"],
	"username_value"=> (string)$params->account->username["value"],
    "password_name"=>(string)$params->account->password["name"],
	"password_value"=> (string)$params->account->password["value"] );
    if (!empty($params->account->reference["value"])) {
        $this->auth['reference_name']  = (string)$params->account->reference['name'];
        $this->auth['reference_value'] = (string)$params->account->reference['value'];
    }
    
	$this->method = (string)$params->method["type"];
    
    $config_path = dirname(SUPPLIERS_CONFIG_FILE)."/";
    $this->services = array();
    $this->services["search"] = array("url"=>(string)$params->services->search["url"],
    "paramsmapfile"=>$config_path.$params->services->search->paramsmap["path"],
    "response_xslt"=>$config_path.$params->services->search->xsltresponse["path"] );
	
    $this->services["booking"] = array( "url"=>(string)$params->services->booking["url"],
    "paramsmapfile"=>$config_path.$params->services->booking->paramsmap["path"],
    "response_xslt"=>$config_path.$params->services->booking->xsltresponse["path"] );
    
    $this->services["details"] = array("url"=>(string)$params->services->details["url"],
    "paramsmapfile"=>$config_path.$params->services->details->paramsmap["path"] );

    $this->services['cancel_booking_info'] = array(
        'url'           => (string)$params->services->cancel_booking_info['url'],
        'paramsmapfile' => $config_path.$params->services->cancel_booking_info->paramsmap['path'],
        'response_xslt' => $config_path.$params->services->cancel_booking_info->xsltresponse['path'],
    );

    $this->services['cancel_booking'] = array(
        'url'           => (string)$params->services->cancel_booking['url'],
        'paramsmapfile' => $config_path.$params->services->cancel_booking->paramsmap['path'],
        'response_xslt' => $config_path.$params->services->cancel_booking->xsltresponse['path'],
    );
  }



    public function build_search_query($params) {
        
        $search_query = ''; 
        $params = $this->map_search_params($params);
        switch($this->code) {
            case 'you':             
                $uri_params = array();
                $uri_params[] = $this->auth["username_name"]."=".$this->auth["username_value"];
                $uri_params[] = $this->auth["password_name"]."=".$this->auth["password_value"];
                foreach ($params as $param=>$value) {
                    $uri_params[] = "$param=$value";
                }
                $search_query = $this->services["search"]["url"]."?".implode("&", $uri_params);
            break;
            case 'low':
                $lowQB = new lowQueryBuilder(array(
                    $this->auth['username_name']  => $this->auth['username_value'],
                    $this->auth['password_name']  => $this->auth['password_value'],
                    $this->auth['reference_name'] => $this->auth['reference_value'],
                ));
                $search_query = array(
                    'url'=>$this->services['search']['url'],
                    'post'=>$lowQB->search($params), //build search query for LowCostBed  -- not necesary anymore
                );                
            break;
            default:
            break;
        }         
        return $search_query;
    }
  
  
  
  
    public function hotel_book($params) {
    $params = $this->map_booking_params($params);
    $url = '';
    switch($this->code) {
        case 'you':
            $uri_params = array();
            $uri_params[] = $this->auth["username_name"]."=".$this->auth["username_value"];
            $uri_params[] = $this->auth["password_name"]."=".$this->auth["password_value"];
            foreach($params as $param=>$value) {
                $uri_params[] = "$param=".urlencode($value);
            }
            $url = $this->services["booking"]["url"]."?".implode("&", $uri_params);
        break;
        case 'low':
            $lowQB = new lowQueryBuilder(array(
                $this->auth['username_name']  => $this->auth['username_value'],
                $this->auth['password_name']  => $this->auth['password_value'],
                $this->auth['reference_name'] => $this->auth['reference_value'],
            ));
            $url = array(
                'url'=>$this->services['booking']['url'],
                'post'=>$lowQB->book($params), //build booking query for LowCostBeds
            );
        break;
    }
    
    // execute booking request
    $queries = array(1=>$url);
    $results = curl_multirequest($queries);
    $result = $results[1];
    $this->log_booking_result($url."\n".$result);
    // transform result XMLs to native XML result format
    $xp = new XsltProcessor();
    // create a DOM document and load the XML datat
    $xml_doc = new DomDocument;
    // create a DOM document and load the XSL stylesheet
    $xsl = new DomDocument;

    $xsl->load($this->get_xslt_path("booking"));
    // import the XSL styelsheet into the XSLT process
    $xp->importStylesheet($xsl);      
    
    if($xml_doc->loadXML($result)) {
      $native = $xp->transformToXml($xml_doc);
      // free objects
      $xsl = null;
      $xml_doc = null;
      $xp = null;
      $results = null;
  
      $xo = simplexml_load_string($native, 'SimpleXMLElement', LIBXML_NOCDATA);
      
      $result = array();
      $result["success"] = (string)$xo->Success;
      $result["booking_ref"] = (string)$xo->Booking_ref;
      $result["voucher_url"] = (string)$xo->Voucher_Url;
      $result["error_msg"] = (string)@$xo->Error_Msg;
    }
    else {
      // error parsing supplier's reply - return system error
      $result = array();
      $result["success"] = "false";
      $result["error_msg"] = "System error: supplier unavailable. Please try to book later or contact site's administration";
    }
    return $result;
  }

    public function cancel_booking($params) {
        $params = $this->map_params($params, $this->load_params_map('cancel_booking_info'));
        $uri_params = array();
        // authentification info
        $uri_params[] = $this->auth["username_name"]."=".$this->auth["username_value"];
        $uri_params[] = $this->auth["password_name"]."=".$this->auth["password_value"];
        foreach ($params as $param=>$value) {
            $uri_params[] = "$param=".urlencode($value);
        }
        $url = $this->services["cancel_booking_info"]["url"]."?".implode("&", $uri_params);
        // execute booking request
        $queries = array(1=>$url);
        $results = curl_multirequest($queries);
        $result = $results[1];

        $this->log_cancel_booking_result($url."\n".$result);

        $params = $this->map_params($params, $this->load_params_map('cancel_booking'));
        $uri_params = array();
        // authentification info
        $uri_params[] = $this->auth["username_name"]."=".$this->auth["username_value"];
        $uri_params[] = $this->auth["password_name"]."=".$this->auth["password_value"];
        foreach ($params as $param=>$value) {
            $uri_params[] = "$param=".urlencode($value);
        }
        $url = $this->services["cancel_booking"]["url"]."?".implode("&", $uri_params);
        // execute booking request
        $queries = array(1=>$url);
        $results = curl_multirequest($queries);
        $result = $results[1];

        $this->log_cancel_booking_result($url."\n".$result);
        
        // transform result XMLs to native XML result format
        $xp = new XsltProcessor();
        // create a DOM document and load the XML datat
        $xml_doc = new DomDocument;
        // create a DOM document and load the XSL stylesheet
        $xsl = new DomDocument;

        $xsl->load($this->get_xslt_path("booking"));
        // import the XSL styelsheet into the XSLT process
        $xp->importStylesheet($xsl);      

        if($xml_doc->loadXML($result)) {
            $native = $xp->transformToXml($xml_doc);

            // free objects
            $xsl = null;
            $xml_doc = null;
            $xp = null;
            $results = null;

            $xo = simplexml_load_string($native, 'SimpleXMLElement', LIBXML_NOCDATA);

            $result = array();
            $result["success"] = (string)$xo->Success;
            $result["booking_ref"] = (string)$xo->Booking_ref;
            $result["error_msg"] = (string)@$xo->Error_Msg;
        } else {
            // error parsing supplier's reply - return system error
            $result = array();
            $result["success"] = "false";
            $result["error_msg"] = "System error: supplier unavailable. Please try to book later or contact site's administration";
        }
        return $result;
    }

  /*public function get_hotel_details($params) {
    $params = $this->map_details_params($params);
    $uri_params = array();
    // authentification info
    $uri_params[] = $this->auth["username_name"]."=".$this->auth["username_value"];
    $uri_params[] = $this->auth["password_name"]."=".$this->auth["password_value"];
    foreach($params as $param=>$value) {
      $uri_params[] = "$param=$value";
    }    
    $url = $this->services["details"]["url"]."?".implode("&", $uri_params);
        
    $xml = file_get_contents($url);
    
    return $xml;    
  }*/

  private function log_booking_result($message) {
    if (MODE_RUN == 'debbug'){
        $filename = "booking-".date("YmdHis");    
        file_put_contents("logs/$filename.xml", $message);    
    }  

  }
  private function log_cancel_booking_result($message) {
    if (MODE_RUN == 'debbug'){
        $filename = "cancel_booking-".date("YmdHis");
        file_put_contents("logs/$filename.xml", $message);            
    }      

  }
  
  public function get_id() {
    return $this->code;
  }  
  public function get_name() {
    return $this->name;
  }
  public function get_xslt_path($type) {
    return $this->services[$type]["response_xslt"];
  }

  protected function load_params_map($map) {
    $params_map = array();
    $fh = fopen($this->services[$map]["paramsmapfile"], "r");
    if(!$fh) throw new Exception("Can't load $map params map file for supplier $this->code");
    while($row = fgetcsv($fh, 1024)) {
      $param_props = array();
      $props_string = explode(";", $row[1]);
      foreach($props_string as $prop) {
        $ret = explode("=", $prop);
        $param_props[$ret[0]] = $ret[1];
      }
      $params_map[$row[0]] = $param_props;
    }
    return $params_map;
  }
  
  protected function load_search_map() {
    if(!$this->search_params_map) {
      $this->search_params_map = $this->load_params_map('search');
    }
  }
  
  protected function load_details_map() {
    if(!$this->details_params_map) {
      $this->details_params_map = $this->load_params_map('details');
    }    
  }

  protected function map_params($params, $map) {
    $result = array();
    foreach($map as $param=>$props) {
      if(isset($props["fname"])) {
        if(isset($params[$props["fname"]])) {
          // if we have value to read from user form - read and format it          
          $value = $params[$props["fname"]];
          if(isset($props["type"])) {
            switch($props["type"]) {
              case "date":
                // format date field according to format
                if(isset($props["format"])) {
                  $value = date($props["format"], $value);
                }
                else {
                  $value = date(SUPPLIER_DEFAULT_DATE_FORMAT, $value);
                }
              break;
            }
          }        
          $result[$param] = $value;
        }
        else {
          // we have no value from user form, try to find default value          
          if(isset($props["default"])) {
            $result[$param] = $props["default"];
          }
          // if no default value - skip parameter
        }
      }
      else {
        // if no fname parameter set - try to use default value for current parapeter
        if(isset($props["default"])) {
          $result[$param] = $props["default"];
        }
      }
    }
    return $result;
  }

  protected function map_search_params($form_params) {
    $this->load_search_map();
    if ($this->code == 'low')
        return $this->map_params(array_merge($form_params['search_params'], $form_params['destination_values']), $this->search_params_map);
    else return $this->map_params($form_params, $this->search_params_map);
    
  }
  
  protected function load_booking_map() {
    if(!$this->booking_params_map) {
      $this->booking_params_map = $this->load_params_map('booking');
    }
  }
  
    protected function load_cancel_booking_map() {
        if (!$this->cancel_booking_params_map) {
            $this->cancel_booking_params_map = $this->load_params_map('cancel_booking');
        }
        return $this->cancel_booking_params_map;
    }
  
  protected function map_booking_params($form_params) {
    $this->load_booking_map();
    return $this->map_params($form_params, $this->booking_params_map);    
  }
  
    protected function map_cancel_booking_params($params) {
        return $this->map_params($params, $this->load_cancel_booking_map());    
    }
  
  protected function map_details_params($params) {
    $this->load_details_map();
    return $this->map_params($params, $this->details_params_map);
  }
                }
